package com.floreantpos.ui.views;

import com.floreantpos.POSConstants;
import com.floreantpos.bo.ui.BackOfficeWindow;
import com.floreantpos.config.PrintConfig;
import com.floreantpos.main.Application;
import com.floreantpos.model.*;
import com.floreantpos.model.dao.ActionHistoryDAO;
import com.floreantpos.model.dao.GuestDAO;
import com.floreantpos.model.dao.TicketDAO;
import com.floreantpos.print.PosPrintService;
import com.floreantpos.services.PosTransactionService;
import com.floreantpos.ui.dialog.*;
import com.floreantpos.ui.views.order.OrderView;
import com.floreantpos.ui.views.order.RootView;
import com.floreantpos.util.POSUtil;
import com.googlecode.floreo.ecf.bematech.BematechMP2100;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.Timer;

/**
 *
 * @author MShahriar
 */
public class SwitchboardView extends JPanel implements ActionListener {

  public final static String VIEW_NAME = com.floreantpos.POSConstants.SWITCHBOARD;

  private Timer ticketListUpdater;
  private int guestID = 0;
  private String taxId = "";

  /**
   * Creates new form SwitchboardView
   */
  public SwitchboardView() {
    initComponents();

    btnBackOffice.addActionListener(this);
    btnEditTicket.addActionListener(this);
    btnGroupSettle.addActionListener(this);
    btnInfo.addActionListener(this);
    btnLogout.addActionListener(this);
    btnManager.addActionListener(this);
    btnECF.addActionListener(this);
    btnNewTicket.addActionListener(this);
    btnDelivery.addActionListener(this);
    btnPrintTicket.addActionListener(this);
    btnReopenTicket.addActionListener(this);
    btnSettleTicket.addActionListener(this);
    btnShutdown.addActionListener(this);
    btnSplitTicket.addActionListener(this);
    btnTakeout.addActionListener(this);
    btnVoidTicket.addActionListener(this);
    btnTableSettle.addActionListener(this);
    btnGuestSettle.addActionListener(this);

    ticketListUpdater = new Timer(30 * 1000, new TicketListUpdaterTask());
  }

  private void initComponents() {

    javax.swing.JPanel statusPanel = new javax.swing.JPanel();
    lblUserName = new javax.swing.JLabel();
    javax.swing.JPanel bottomPanel = new javax.swing.JPanel();
    javax.swing.JPanel bottomLeftPanel = new javax.swing.JPanel();
    openTicketList = new com.floreantpos.ui.TicketListView();
    javax.swing.JPanel activityPanel = new javax.swing.JPanel();
    btnInfo = new com.floreantpos.swing.PosButton();
    btnNewTicket = new com.floreantpos.swing.PosButton();
    btnEditTicket = new com.floreantpos.swing.PosButton();
    btnSplitTicket = new com.floreantpos.swing.PosButton();
    btnVoidTicket = new com.floreantpos.swing.PosButton();
    btnReopenTicket = new com.floreantpos.swing.PosButton();
    btnSettleTicket = new com.floreantpos.swing.PosButton();
    btnGroupSettle = new com.floreantpos.swing.PosButton();
    btnTableSettle = new com.floreantpos.swing.PosButton();
    btnTakeout = new com.floreantpos.swing.PosButton();
    btnPrintTicket = new com.floreantpos.swing.PosButton();
    btnDelivery = new com.floreantpos.swing.PosButton();
    javax.swing.JPanel bottomRightPanel = new javax.swing.JPanel();
    btnShutdown = new com.floreantpos.swing.PosButton();
    btnLogout = new com.floreantpos.swing.PosButton();
    btnBackOffice = new com.floreantpos.swing.PosButton();
    btnManager = new com.floreantpos.swing.PosButton();
    btnECF = new com.floreantpos.swing.PosButton();
    btnGuestSettle = new com.floreantpos.swing.PosButton();

    setLayout(new java.awt.BorderLayout(10, 10));

    lblUserName.setFont(new java.awt.Font("Tahoma", 1, 18));
    lblUserName.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
    statusPanel.add(lblUserName, java.awt.BorderLayout.PAGE_START);

    add(statusPanel, java.awt.BorderLayout.NORTH);

    bottomPanel.setLayout(new java.awt.BorderLayout(5, 5));

    bottomLeftPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(null, POSConstants.OPEN_TICKETS_AND_ACTIVITY, javax.swing.border.TitledBorder.CENTER, javax.swing.border.TitledBorder.DEFAULT_POSITION));
    bottomLeftPanel.setLayout(new java.awt.BorderLayout(5, 5));
    bottomLeftPanel.add(openTicketList, java.awt.BorderLayout.CENTER);

    activityPanel.setPreferredSize(new java.awt.Dimension(655, 160));
    activityPanel.setLayout(new java.awt.GridLayout(3, 0, 5, 5));

    btnNewTicket.setIcon(new javax.swing.ImageIcon(getClass().getResource("/images/new_ticket_32.png")));
    btnNewTicket.setText(POSConstants.CAPITAL_NEW);
    btnNewTicket.setPreferredSize(new java.awt.Dimension(120, 50));
    activityPanel.add(btnNewTicket);

    btnTakeout.setIcon(new javax.swing.ImageIcon(getClass().getResource("/images/new_ticket_32.png")));
    btnTakeout.setText(POSConstants.CAPITAL_TAKE_OUT);
    btnTakeout.setPreferredSize(new java.awt.Dimension(160, 60));
    activityPanel.add(btnTakeout);

    btnDelivery.setIcon(new javax.swing.ImageIcon(getClass().getResource("/images/new_ticket_32.png")));
    btnDelivery.setText(com.floreantpos.POSConstants.DELIVERY);
    btnDelivery.setPreferredSize(new java.awt.Dimension(160, 60));
    activityPanel.add(btnDelivery);

    btnPrintTicket.setIcon(new javax.swing.ImageIcon(getClass().getResource("/images/print_32.png")));
    btnPrintTicket.setText(POSConstants.CAPITAL_PRINT);
    btnPrintTicket.setPreferredSize(new java.awt.Dimension(120, 50));
    activityPanel.add(btnPrintTicket);

    btnEditTicket.setIcon(new javax.swing.ImageIcon(getClass().getResource("/images/edit_ticket_32.png")));
    btnEditTicket.setText(POSConstants.CAPITAL_EDIT);
    btnEditTicket.setPreferredSize(new java.awt.Dimension(120, 50));
    activityPanel.add(btnEditTicket);

    btnSplitTicket.setIcon(new javax.swing.ImageIcon(getClass().getResource("/images/edit_ticket_32.png")));
    btnSplitTicket.setText(POSConstants.CAPITAL_SPLIT);
    btnSplitTicket.setPreferredSize(new java.awt.Dimension(120, 50));
    activityPanel.add(btnSplitTicket);

    btnReopenTicket.setIcon(new javax.swing.ImageIcon(getClass().getResource("/images/edit_ticket_32.png")));
    btnReopenTicket.setText(POSConstants.CAPITAL_RE_OPEN);
    btnReopenTicket.setPreferredSize(new java.awt.Dimension(120, 50));
    activityPanel.add(btnReopenTicket);

    btnVoidTicket.setIcon(new javax.swing.ImageIcon(getClass().getResource("/images/void_ticket_32.png")));
    btnVoidTicket.setText(POSConstants.CAPITAL_VOID);
    btnVoidTicket.setPreferredSize(new java.awt.Dimension(120, 50));
    activityPanel.add(btnVoidTicket);

    btnInfo.setIcon(new javax.swing.ImageIcon(getClass().getResource("/images/settle_ticket_32.png")));
    btnInfo.setText(POSConstants.CAPITAL_INFO);
    btnInfo.setPreferredSize(new java.awt.Dimension(160, 60));
    activityPanel.add(btnInfo);

    btnSettleTicket.setIcon(new javax.swing.ImageIcon(getClass().getResource("/images/settle_ticket_32.png")));
    btnSettleTicket.setText(POSConstants.CAPITAL_SETTLE);
    btnSettleTicket.setPreferredSize(new java.awt.Dimension(160, 60));
    activityPanel.add(btnSettleTicket);

    btnGroupSettle.setIcon(new javax.swing.ImageIcon(getClass().getResource("/images/settle_ticket_32.png")));
    btnGroupSettle.setText("<html><body>" + POSConstants.CAPITAL_SETTLE + "<br>" + POSConstants.CAPITAL_GROUP + "</body></html>");
    btnGroupSettle.setPreferredSize(new java.awt.Dimension(160, 60));
    activityPanel.add(btnGroupSettle);

    btnTableSettle.setIcon(new javax.swing.ImageIcon(getClass().getResource("/images/settle_ticket_32.png")));
    btnTableSettle.setText("<html><body>" + POSConstants.CAPITAL_SETTLE + "<br>" + com.floreantpos.POSConstants.TABLE + "</body></html>");
    btnTableSettle.setPreferredSize(new java.awt.Dimension(160, 60));
    activityPanel.add(btnTableSettle);

    bottomLeftPanel.add(activityPanel, java.awt.BorderLayout.SOUTH);

    bottomPanel.add(bottomLeftPanel, java.awt.BorderLayout.CENTER);

    bottomRightPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "Outros", javax.swing.border.TitledBorder.CENTER, javax.swing.border.TitledBorder.DEFAULT_POSITION));
    bottomRightPanel.setPreferredSize(new java.awt.Dimension(200, 10));

    btnShutdown.setText(POSConstants.CAPITAL_SHUTDOWN);

    btnLogout.setText(POSConstants.CAPITAL_LOGOUT);

    btnBackOffice.setText(POSConstants.CAPITAL_BACK_OFFICE);

    btnManager.setText(POSConstants.CAPITAL_MANAGER);

    btnECF.setText("Funções do ECF");

    btnGuestSettle.setText(POSConstants.RECEIVE);

    org.jdesktop.layout.GroupLayout bottomRightPanelLayout = new org.jdesktop.layout.GroupLayout(bottomRightPanel);
    bottomRightPanel.setLayout(bottomRightPanelLayout);
    bottomRightPanelLayout.setHorizontalGroup(
            bottomRightPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(bottomRightPanelLayout.createSequentialGroup().addContainerGap()
                    .add(bottomRightPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                            .add(btnShutdown, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 168, Short.MAX_VALUE)
                            .add(btnLogout, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 168, Short.MAX_VALUE)
                            .add(btnGuestSettle, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 168, Short.MAX_VALUE)
                            .add(btnManager, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 168, Short.MAX_VALUE)
                            .add(btnBackOffice, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 168, Short.MAX_VALUE)
                            .add(btnECF, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 168, Short.MAX_VALUE))
                    .addContainerGap()));
    bottomRightPanelLayout.setVerticalGroup(
            bottomRightPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(org.jdesktop.layout.GroupLayout.TRAILING, bottomRightPanelLayout.createSequentialGroup()
                    .addContainerGap(39, Short.MAX_VALUE)
                    .add(btnECF, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                    .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                    .add(btnBackOffice, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                    .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                    .add(btnManager, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                    .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                    .add(btnGuestSettle, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                    .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                    .add(btnLogout, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                    .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED).add(btnShutdown, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 58, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                    .addContainerGap()));

    bottomRightPanelLayout.linkSize(new java.awt.Component[]{btnECF, btnGuestSettle, btnBackOffice, btnLogout, btnManager, btnShutdown}, org.jdesktop.layout.GroupLayout.VERTICAL);

    bottomPanel.add(bottomRightPanel, java.awt.BorderLayout.EAST);

    add(bottomPanel, java.awt.BorderLayout.CENTER);
  }

  private void doReopenTicket() {
    NumberSelectionDialog2 dialog = new NumberSelectionDialog2();
    dialog.setTitle(POSConstants.ENTER_TICKET_ID);
    dialog.pack();
    dialog.open();

    if (dialog.isCanceled()) {
      return;
    }

    int ticketId = (int) dialog.getValue();
    TicketDAO dao = new TicketDAO();
    Ticket ticket = dao.get(Integer.valueOf(ticketId));
    if (ticket == null) {
      POSMessageDialog.showError(com.floreantpos.POSConstants.TICKET + ticketId + com.floreantpos.POSConstants.NOT + POSConstants.FOUND);
      return;
    }
    if (!ticket.isClosed()) {
      POSMessageDialog.showError(POSConstants.TICKET_IS_NOT_CLOSED);
      return;
    }
    if (ticket.isVoided()) {
      POSMessageDialog.showError(com.floreantpos.POSConstants.CANCELED_ORDER_CANNOT_REOPEN);
      return;
    }

    String amount = "";
    if (ticket.getGratuity() != null) {
      amount = Application.getCurrencySymbol() + " " + Application.formatNumber(ticket.getTotalAmount() + ticket.getGratuity().getAmount());
    } else {
      amount = Application.getCurrencySymbol() + " " + Application.formatNumber(ticket.getTotalAmount());
    }

    String message = "";
    String amountMessage = "";
    if (ticket.getTransactionType().equals(PosTransaction.TYPE_CASH)) {
      amountMessage = "<span style='color: red; font-weight: bold;'>" + amount + "</span>";
      message = "<html><body><h3>O pedido será reaberto. Antes disso você deve retirar " + amountMessage + " do caixa. Continuar?</h3></body></html>";
    } else {
      message = "<html><body><h3>O pedido será reaberto. Continuar?</h3></body></html>";
    }
    int option = JOptionPane.showOptionDialog(this, message, com.floreantpos.POSConstants.ATTENTION, JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, null, null, null);
    if (option != JOptionPane.YES_OPTION) {
      return;
    }

    try {
      Double paidAmount = Double.valueOf(0);
      if (ticket.getGratuity() == null) {
        paidAmount = ticket.getPaidAmount();
      } else {
        paidAmount = ticket.getPaidAmount() + ticket.getGratuity().getAmount();
      }
      PosTransactionService service = PosTransactionService.getInstance();
      service.refundTicket(ticket);

      ActionHistoryDAO.getInstance().saveHistory(Application.getCurrentUser(), ActionHistory.REOPEN_CHECK, "Ped." + ":" + ticket.getId());

      if (ticket.getTransactionType().equals(PosTransaction.TYPE_CASH)) {
        JOptionPane.showMessageDialog(this, "<html><body>Confirme a retirada de " + amountMessage + " do caixa.</body></html>");
      }

      ticket.setDrawerResetted(false);

      if (!ticket.isPaymentTicket()) {
        editTicket(ticket);
      }
    } catch (Exception e) {
      POSMessageDialog.showError(this, POSConstants.ERROR_MESSAGE, e);
    }
  }

  private synchronized void doShowBackoffice() {
    BackOfficeWindow window = Application.getInstance().getBackOfficeWindow();
    if (window == null) {
      window = new BackOfficeWindow();
      Application.getInstance().setBackOfficeWindow(window);
    }
    window.setVisible(true);
    window.toFront();
  }

  private void doShutdown() {
    Application.getInstance().shutdownPOS();
  }

  private void doLogout() {
    Application.getInstance().logout();
  }

  private Ticket registeredGuestPaymentTicket(int guestID, String guestName, Double paymentAmount) {
    Application application = Application.getInstance();
    Calendar currentTime = Calendar.getInstance();

    Ticket ticket = new Ticket();
    ticket.setTableNumber(Ticket.TAKE_OUT);
    ticket.setGuest(guestName + com.floreantpos.POSConstants.PAYMENT);
    ticket.setRegisteredGuest(guestID);
    ticket.setPaymentTicket(Boolean.TRUE);
    ticket.setTerminal(application.getTerminal());
    ticket.setOwner(Application.getCurrentUser());
    ticket.setShift(application.getCurrentShift());
    ticket.setCreateDate(currentTime.getTime());
    ticket.setCreationHour(currentTime.get(Calendar.HOUR_OF_DAY));
    ticket.setDueAmount(paymentAmount);
    ticket.setSubtotalAmount(paymentAmount);
    ticket.setTotalAmount(paymentAmount);
    ticket.setDiscountAmount(Double.valueOf(0));
    ticket.setPaidAmount(Double.valueOf(0));
    ticket.setTaxAmount(Double.valueOf(0));

    TicketItem ticketItem = new TicketItem();
    ticketItem.setTicket(ticket);
    ticketItem.setBeverage(Boolean.FALSE);
    ticketItem.setBuffet(Boolean.FALSE);
    ticketItem.setCategoryName(com.floreantpos.POSConstants.PAYMENTS);
    ticketItem.setDiscountAmount(Double.valueOf(0));
    ticketItem.setDiscountRate(Double.valueOf(0));
    ticketItem.setGroupName(com.floreantpos.POSConstants.PAYMENTS);
    ticketItem.setHasModifiers(Boolean.FALSE);
    ticketItem.setItemCount(1);
    ticketItem.setItemId(0);
    ticketItem.setModifiedTime(currentTime.getTime());
    ticketItem.setName(com.floreantpos.POSConstants.CAPITAL_PAY_OUT);
    ticketItem.setPrintedToKitchen(Boolean.FALSE);
    ticketItem.setShouldPrintToKitchen(Boolean.FALSE);
    ticketItem.setSubtotalAmount(paymentAmount);
    ticketItem.setSubtotalAmountWithoutModifiers(paymentAmount);
    ticketItem.setTableRowNum(0);
    ticketItem.setTaxAmount(Double.valueOf(0));
    ticketItem.setTaxAmountWithoutModifiers(Double.valueOf(0));
    ticketItem.setTaxRate(Double.valueOf(0));
    ticketItem.setTotalAmount(Double.valueOf(0));
    ticketItem.setTotalAmountWithoutModifiers(Double.valueOf(0));
    ticketItem.setUnitPrice(paymentAmount);
    ticketItem.setPaymentItem(Boolean.TRUE);
    ticketItem.setUpdateTime(new Date());

    ticket.addToticketItems(ticketItem);

    return ticket;
  }

  private Ticket guestPaymentTicket(Double paymentAmount) {
    Application application = Application.getInstance();
    Calendar currentTime = Calendar.getInstance();

    Ticket ticket = new Ticket();
    ticket.setTableNumber(Ticket.TAKE_OUT);
    ticket.setGuest(com.floreantpos.POSConstants.PAYMENT);
    ticket.setPaymentTicket(Boolean.TRUE);
    ticket.setTerminal(application.getTerminal());
    ticket.setOwner(Application.getCurrentUser());
    ticket.setShift(application.getCurrentShift());
    ticket.setCreateDate(currentTime.getTime());
    ticket.setCreationHour(currentTime.get(Calendar.HOUR_OF_DAY));
    ticket.setDueAmount(paymentAmount);
    ticket.setSubtotalAmount(paymentAmount);
    ticket.setTotalAmount(paymentAmount);
    ticket.setDiscountAmount(Double.valueOf(0));
    ticket.setPaidAmount(Double.valueOf(0));
    ticket.setTaxAmount(Double.valueOf(0));

    TicketItem ticketItem = new TicketItem();
    ticketItem.setTicket(ticket);
    ticketItem.setBeverage(Boolean.FALSE);
    ticketItem.setBuffet(Boolean.FALSE);
    ticketItem.setCategoryName(com.floreantpos.POSConstants.PAYMENTS);
    ticketItem.setDiscountAmount(Double.valueOf(0));
    ticketItem.setDiscountRate(Double.valueOf(0));
    ticketItem.setGroupName(com.floreantpos.POSConstants.PAYMENTS);
    ticketItem.setHasModifiers(Boolean.FALSE);
    ticketItem.setItemCount(1);
    ticketItem.setItemId(0);
    ticketItem.setModifiedTime(currentTime.getTime());
    ticketItem.setName(com.floreantpos.POSConstants.CAPITAL_PAY_OUT);
    ticketItem.setPrintedToKitchen(Boolean.FALSE);
    ticketItem.setShouldPrintToKitchen(Boolean.FALSE);
    ticketItem.setSubtotalAmount(paymentAmount);
    ticketItem.setSubtotalAmountWithoutModifiers(paymentAmount);
    ticketItem.setTableRowNum(0);
    ticketItem.setTaxAmount(Double.valueOf(0));
    ticketItem.setTaxAmountWithoutModifiers(Double.valueOf(0));
    ticketItem.setTaxRate(Double.valueOf(0));
    ticketItem.setTotalAmount(Double.valueOf(0));
    ticketItem.setTotalAmountWithoutModifiers(Double.valueOf(0));
    ticketItem.setUnitPrice(paymentAmount);
    ticketItem.setPaymentItem(Boolean.TRUE);
    ticketItem.setUpdateTime(new Date());

    ticket.addToticketItems(ticketItem);

    return ticket;
  }

  private void registeredGuestSettle(int guestID, String guestName, Double paymentAmount) {
    try {
      PaymentTypeSelectionDialog dialog = new PaymentTypeSelectionDialog(false, guestID, null);
      dialog.setSize(250, 400);
      dialog.open();

      if (!dialog.isCanceled()) {
        Ticket ticket = registeredGuestPaymentTicket(guestID, guestName, paymentAmount);
        ticket = TicketDAO.getInstance().initializeTicket(ticket);

        SettleTicketView view = SettleTicketView.getInstance();
        view.setPaymentView(dialog.getSelectedPaymentView());
        view.setCurrentTicket(ticket);
        RootView.getInstance().showView(SettleTicketView.VIEW_NAME);
      }
    } catch (Exception e) {
      POSMessageDialog.showError(POSConstants.ERROR_MESSAGE, e);
    }
  }

  private void guestSettle(Double paymentAmount) {
    try {
      PaymentTypeSelectionDialog dialog = new PaymentTypeSelectionDialog(false, guestID, null);
      dialog.setSize(250, 400);
      dialog.open();

      if (!dialog.isCanceled()) {
        Ticket ticket = guestPaymentTicket(paymentAmount);
        ticket = TicketDAO.getInstance().initializeTicket(ticket);

        SettleTicketView view = SettleTicketView.getInstance();
        view.setPaymentView(dialog.getSelectedPaymentView());
        view.setCurrentTicket(ticket);
        RootView.getInstance().showView(SettleTicketView.VIEW_NAME);
      }
    } catch (Exception e) {
      POSMessageDialog.showError(POSConstants.ERROR_MESSAGE, e);
    }
  }

  private void doGuestSettle() {
    String guestPhone = null;

    TelephoneSelectionDialog phoneDialog = new TelephoneSelectionDialog();
    phoneDialog.setTitle(com.floreantpos.POSConstants.CUSTOMER_PHONE);
    phoneDialog.pack();
    phoneDialog.open();

    if (phoneDialog.isCanceled()) {
      NumberSelectionDialog2 dialog = new NumberSelectionDialog2();
      dialog.setTitle(com.floreantpos.POSConstants.AMOUNT_PAID_OUT);
      dialog.setFloatingPoint(true);
      dialog.pack();
      dialog.open();

      if (dialog.isCanceled()) {
        return;
      }

      Double paymentAmount = Double.valueOf(dialog.getValue());
      if (paymentAmount == 0) {
        POSMessageDialog.showError(this, com.floreantpos.POSConstants.PAYMENT_VALUE_ZERO);
        return;
      }

      guestSettle(paymentAmount);
    } else {
      guestPhone = phoneDialog.getValue();
      GuestDAO dao = GuestDAO.getInstance();
      Guest registeredGuest = null;
      registeredGuest = dao.findGuestByTelephone(guestPhone);

      if (registeredGuest == null) {
        int option = JOptionPane.showOptionDialog(this, com.floreantpos.POSConstants.CUSTOMER_NOT_FOUND, POSConstants.CONFIRM, JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, new String[]{"Cadastrar", "Procurar Novamente", "Cancelar"}, null);
        if (option == JOptionPane.YES_OPTION) {
          GuestDialog guestDialog = new GuestDialog(Application.getPosWindow(), true, guestPhone);
          guestDialog.open();

          registeredGuest = dao.findGuestByTelephone(guestPhone);
          if (registeredGuest == null) {
            POSMessageDialog.showError(com.floreantpos.POSConstants.ENTER_PHONE_NUMBER_AGAIN);
            doGuestSettle();
          }
        } else if (option == JOptionPane.NO_OPTION) {
          doGuestSettle();
        } else {
          return;
        }
      }
      guestID = registeredGuest.getId();
      String guestName = registeredGuest.getName();
      String guestPhoneNumber = registeredGuest.getTelephone();
      Double guestDueAmount = registeredGuest.getCurrentBalance();

      if (guestDueAmount == 0) {
        POSMessageDialog.showMessage(com.floreantpos.POSConstants.NO_OUTSTANDING_BALANCE);
        NumberSelectionDialog2 dialog = new NumberSelectionDialog2();
        dialog.setTitle(com.floreantpos.POSConstants.AMOUNT_PAID_OUT);
        dialog.setFloatingPoint(true);
        dialog.pack();
        dialog.open();

        if (dialog.isCanceled()) {
          return;
        }

        Double paymentAmount = Double.valueOf(dialog.getValue());
        if (paymentAmount == 0) {
          POSMessageDialog.showError(this, com.floreantpos.POSConstants.PAYMENT_VALUE_ZERO);
          return;
        }
        registeredGuestSettle(guestID, guestName, paymentAmount);
      }

      if (guestDueAmount > 0) {
        POSMessageDialog.showMessage(com.floreantpos.POSConstants.GUEST + guestName + " - " + guestPhoneNumber + "\nSaldo atual: R$ " + Application.formatNumber(guestDueAmount) + " (Crédito a favor do Cliente).\nEntre com um valor para o pagamento.");
        NumberSelectionDialog2 dialog = new NumberSelectionDialog2();
        dialog.setTitle(com.floreantpos.POSConstants.AMOUNT_PAID_OUT);
        dialog.setFloatingPoint(true);
        dialog.pack();
        dialog.open();

        if (dialog.isCanceled()) {
          return;
        }

        Double paymentAmount = Double.valueOf(dialog.getValue());
        if (paymentAmount == 0) {
          POSMessageDialog.showError(this, com.floreantpos.POSConstants.PAYMENT_VALUE_ZERO);
          return;
        }
        registeredGuestSettle(guestID, guestName, paymentAmount);
      }

      if (guestDueAmount < 0) {
        POSMessageDialog.showMessage(com.floreantpos.POSConstants.CUSTOMER_DOTS + guestName + " - " + guestPhoneNumber + "\nSaldo atual: R$ " + Application.formatNumber(guestDueAmount) + " (Saldo devedor do Cliente).\nEntre com o valor para o pagamento.");
        guestDueAmount = guestDueAmount * -1;
        NumberSelectionDialog2 dialog = new NumberSelectionDialog2();
        dialog.setTitle(com.floreantpos.POSConstants.AMOUNT_PAID_OUT);
        dialog.setFloatingPoint(true);
        dialog.setValue(guestDueAmount);
        dialog.pack();
        dialog.open();

        if (dialog.isCanceled()) {
          return;
        }

        Double paymentAmount = Double.valueOf(dialog.getValue());
        if (paymentAmount == 0) {
          POSMessageDialog.showError(this, com.floreantpos.POSConstants.PAYMENT_VALUE_ZERO);
          return;
        }
        registeredGuestSettle(guestID, guestName, paymentAmount);
      }
    }
  }

  private void doSettleTicket() {
    try {
      List<Ticket> selectedTickets = openTicketList.getSelectedTickets();
      if (selectedTickets.size() == 0 || selectedTickets.size() > 1) {
        POSMessageDialog.showMessage(com.floreantpos.POSConstants.SELECT_ONE_REQUEST_TO_CLOSE);
        return;
      }

      Ticket ticket = selectedTickets.get(0);

      if (ticket.isPaymentTicket()) {
        POSMessageDialog.showMessage("Pagamentos não podem ser fechados da mesma maneira que contas.\nPor favor, cancele este pagamento e caso necessário registre novamente através do botão \"Receber\".");
        return;
      }

      if (Application.isSaveTaxId()) {
        taxId = POSUtil.getTaxId();
      }
      
      PaymentTypeSelectionDialog dialog = null;
      if (ticket.getRegisteredGuest() != null) {
        dialog = new PaymentTypeSelectionDialog(true, ticket.getRegisteredGuest(), taxId);
      } else {
        dialog = new PaymentTypeSelectionDialog(taxId);
      }

      dialog.setSize(250, 400);
      dialog.open();

      if (!dialog.isCanceled()) {
        ticket = TicketDAO.getInstance().initializeTicket(ticket);

        SettleTicketView view = SettleTicketView.getInstance();
        view.setPaymentView(dialog.getSelectedPaymentView());
        view.setCurrentTicket(ticket);
        RootView.getInstance().showView(SettleTicketView.VIEW_NAME);
      }
    } catch (Exception e) {
      POSMessageDialog.showError(POSConstants.ERROR_MESSAGE, e);
    }
  }

  private void doPrintTicket() {
    List<Ticket> selectedTickets = openTicketList.getSelectedTickets();
    if (selectedTickets.size() == 0 || selectedTickets.size() > 1) {
      POSMessageDialog.showMessage(POSConstants.SELECT_ONE_TICKET_TO_PRINT);
      return;
    }

    Ticket ticket = selectedTickets.get(0);
    try {
      ticket = TicketDAO.getInstance().initializeTicket(ticket);

      if (!ticket.isPrintedTicket()) {
        ticket.setPrintedTicket(true);
      }

      PosPrintService.printTicket(ticket);

      String actionMessage = com.floreantpos.POSConstants.CHK_NO + ticket.getId();
      ActionHistoryDAO.getInstance().saveHistory(Application.getCurrentUser(), ActionHistory.PRINT_CHECK, actionMessage);
    } catch (Exception e) {
      POSMessageDialog.showError(this, e.getMessage(), e);
    }
  }

  private void doVoidTicket() {
    try {
      List<Ticket> selectedTickets = openTicketList.getSelectedTickets();
      if (selectedTickets.size() == 0 || selectedTickets.size() > 1) {
        POSMessageDialog.showMessage(POSConstants.SELECT_ONE_TICKET_TO_VOID);
        return;
      }

      Ticket ticket = selectedTickets.get(0);

      if (!ticket.getTotalAmount().equals(ticket.getDueAmount())) {
        POSMessageDialog.showMessage(POSConstants.PARTIAL_PAID_VOID_ERROR);
        return;
      }

      ticket = TicketDAO.getInstance().initializeTicket(ticket);

      VoidTicketDialog voidTicketDialog = new VoidTicketDialog(Application.getPosWindow(), true);
      voidTicketDialog.setTicket(ticket);
      voidTicketDialog.open();

      if (!voidTicketDialog.isCanceled()) {
        updateView();
      }
    } catch (Exception e) {
      POSMessageDialog.showError(POSConstants.ERROR_MESSAGE, e);
    }
  }

  private void doSplitTicket() {
    try {
      List<Ticket> selectedTickets = openTicketList.getSelectedTickets();
      if (selectedTickets.size() == 0 || selectedTickets.size() > 1) {
        POSMessageDialog.showMessage(POSConstants.SELECT_ONE_TICKET_TO_SPLIT);
        return;
      }

      Ticket ticket = selectedTickets.get(0);
      if (!ticket.getTotalAmount().equals(ticket.getDueAmount())) {
        POSMessageDialog.showMessage(POSConstants.PARTIAL_PAID_VOID_ERROR);
        return;
      }

      if (ticket.isPaymentTicket()) {
        POSMessageDialog.showMessage(com.floreantpos.POSConstants.PAYMENT_CANNOT_DIVIDED);
        return;
      }

      ticket = TicketDAO.getInstance().initializeTicket(ticket);

      SplitTicketDialog dialog = new SplitTicketDialog();
      dialog.setTicket(ticket);
      dialog.open();

      updateView();
    } catch (Exception e) {
      POSMessageDialog.showError(POSConstants.ERROR_MESSAGE, e);
    }
  }

  private void doEditTicket() {
    List<Ticket> selectedTickets = openTicketList.getSelectedTickets();
    if (selectedTickets.size() == 0 || selectedTickets.size() > 1) {
      POSMessageDialog.showMessage(POSConstants.SELECT_ONE_TICKET_TO_EDIT);
      return;
    }

    Ticket ticket = selectedTickets.get(0);

    if (ticket.isPaymentTicket()) {
      POSMessageDialog.showMessage(com.floreantpos.POSConstants.PAYMENT_CANNOT_MODIFIED);
      return;
    }

    editTicket(ticket);
  }

  private void editTicket(Ticket ticket) {
    ticket = TicketDAO.getInstance().initializeTicket(ticket);

    OrderView.getInstance().setCurrentTicket(ticket);
    RootView.getInstance().showView(OrderView.VIEW_NAME);
  }

  private void doCreateNewTicket() {
    createNewTicket();
  }

  private void createNewTicket() {
    int tableNumber = 0;
    String guestName = null;

    TicketDAO dao = TicketDAO.getInstance();
    Ticket ticket = null;

    if (Application.isSaveGuestName()) {

      NotesDialog guestNameDialog = new NotesDialog(Application.getPosWindow(), true);
      guestNameDialog.setTitle(com.floreantpos.POSConstants.CUSTOMER_NAME);
      guestNameDialog.open();

      if (guestNameDialog.isCanceled()) {
        return;
      }

      guestName = guestNameDialog.getNote();

      if (guestName.isEmpty()) {
        POSMessageDialog.showError(this, com.floreantpos.POSConstants.CUSTOMER_NAME_REQUIRED);
        return;
      }
    } else if (Application.isAutoGenTicket()) {

      tableNumber = dao.findNextTableNumber();

    } else {

      NumberSelectionDialog2 dialog = new NumberSelectionDialog2();
      dialog.setTitle(POSConstants.ENTER_A_TABLE_NUMBER);
      dialog.pack();
      dialog.open();

      if (dialog.isCanceled()) {
        return;
      }

      tableNumber = (int) dialog.getValue();
      if (tableNumber == 0) {
        POSMessageDialog.showError(this, POSConstants.TABLE_NUMBER_CANNOT_BE_0);
        return;
      }
      if (tableNumber > 999) {
        POSMessageDialog.showError(this, "Número de Controle Inválido\n(Número de controle deve estar entre 1 e 999)");
        return;
      }

    }

    if (Application.isSaveGuestName()) {
      ticket = dao.findTicketByGuestName(guestName);
    } else {
      ticket = dao.findTicketByTableNumber(tableNumber);
    }

    if (ticket != null && !Application.isAutoGenTicket()) {
      String existingOrderMessage = com.floreantpos.POSConstants.ORDER_ALREADY_EXIST;
      if (Application.isSaveGuestName()) {
        existingOrderMessage = existingOrderMessage + com.floreantpos.POSConstants.THIS_1 + Application.getControlTypeIdentifier() + ", o que você deseja?";
      } else {
        existingOrderMessage = existingOrderMessage + com.floreantpos.POSConstants.THIS_2 + Application.getControlTypeIdentifier() + ", o que você deseja?";
      }
      int option = JOptionPane.showOptionDialog(this, existingOrderMessage, POSConstants.CONFIRM, JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, new String[]{"Incluir Novo Pedido", "Alterar Pedido Existente", "Cancelar"}, null);
      if (option == JOptionPane.YES_OPTION) {
        //fall down to create new ticket.
      } else if (option == JOptionPane.NO_OPTION) {
        tableNumber = ticket.getTableNumber();
        editTicket(ticket);
        return;
      } else {
        return;
      }
    }

    int numberOfGuests = 1;

    if (Application.isSaveGuestsPerTable()) {
      NumberSelectionDialog2 dialog = new NumberSelectionDialog2();
      dialog.setTitle(POSConstants.ENTER_NUMBER_OF_GUEST);
      dialog.setValue(0);
      dialog.pack();
      dialog.open();

      if (dialog.isCanceled()) {
        return;
      }
      numberOfGuests = (int) dialog.getValue();
      if (numberOfGuests == 0) {
        POSMessageDialog.showError(this, POSConstants.GUEST_NUMBER_CANNOT_BE_0);
        return;
      }
    }

    if ((Application.isSaveGuestName() && tableNumber == 0) || (Application.isAutoGenTicket() && ticket != null)) {

      if (ticket != null) {
        tableNumber = 0;
      }

      int autoTableNumber = 1;

      do {
        ticket = dao.findTicketByTableNumber(autoTableNumber);
        if (ticket == null) {
          tableNumber = autoTableNumber;
        } else {
          autoTableNumber = autoTableNumber + 1;
        }
      } while (tableNumber == 0);
    }

    if (!Application.isSaveGuestName()) {
      DecimalFormat numberFormat = new DecimalFormat("#,##0", new DecimalFormatSymbols(new Locale("pt", "BR")));
      guestName = String.valueOf(numberFormat.format(tableNumber));
    }

    Application application = Application.getInstance();

    ticket = new Ticket();
    ticket.setTableNumber(tableNumber);
    ticket.setNumberOfGuests(numberOfGuests);
    ticket.setGuest(guestName);
    ticket.setTerminal(application.getTerminal());
    ticket.setOwner(Application.getCurrentUser());
    ticket.setShift(application.getCurrentShift());

    Calendar currentTime = Calendar.getInstance();
    ticket.setCreateDate(currentTime.getTime());
    ticket.setCreationHour(currentTime.get(Calendar.HOUR_OF_DAY));

    OrderView.getInstance().setCurrentTicket(ticket);
    RootView.getInstance().showView(OrderView.VIEW_NAME);
  }

  private void doTakeout() {

    String guestName = null;

    NotesDialog guestNameDialog = new NotesDialog(Application.getPosWindow(), true);
    guestNameDialog.setTitle(com.floreantpos.POSConstants.CUSTOMER_NAME);
    guestNameDialog.open();

    if (guestNameDialog.isCanceled()) {
      return;
    }

    guestName = guestNameDialog.getNote();

    if (guestName.isEmpty()) {
      guestName = com.floreantpos.POSConstants.TO_GO;
    } else {
      guestName = guestName + com.floreantpos.POSConstants.TO_GO;
    }

    Application application = Application.getInstance();

    Ticket ticket = new Ticket();
    ticket.setTableNumber(Ticket.TAKE_OUT);
    ticket.setGuest(guestName);
    ticket.setTerminal(application.getTerminal());
    ticket.setOwner(Application.getCurrentUser());
    ticket.setShift(application.getCurrentShift());

    Calendar currentTime = Calendar.getInstance();
    ticket.setCreateDate(currentTime.getTime());
    ticket.setCreationHour(currentTime.get(Calendar.HOUR_OF_DAY));

    OrderView.getInstance().setCurrentTicket(ticket);
    RootView.getInstance().showView(OrderView.VIEW_NAME);
  }

  private void doDelivery() {

    String guestPhone = null;

    TelephoneSelectionDialog phoneDialog = new TelephoneSelectionDialog();
    phoneDialog.setTitle(com.floreantpos.POSConstants.CUSTOMER_PHONE);
    phoneDialog.pack();
    phoneDialog.open();

    if (phoneDialog.isCanceled()) {
      return;
    }

    guestPhone = phoneDialog.getValue();

    GuestDAO dao = GuestDAO.getInstance();

    Guest registeredGuest = null;

    registeredGuest = dao.findGuestByTelephone(guestPhone);

    if (registeredGuest == null) {
      int option = JOptionPane.showOptionDialog(this, com.floreantpos.POSConstants.CUSTOMER_NOT_FOUND, POSConstants.CONFIRM, JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, new String[]{"Cadastrar", "Procurar Novamente", "Cancelar"}, null);
      if (option == JOptionPane.YES_OPTION) {
        GuestDialog guestDialog = new GuestDialog(Application.getPosWindow(), true, guestPhone);
        guestDialog.open();

        registeredGuest = dao.findGuestByTelephone(guestPhone);
        if (registeredGuest == null) {
          POSMessageDialog.showError("O Cliente não foi cadastrado ou o telefone cadastrado é diferente do digitado anteriormente.\nPor favor, entre com o número novamente.");
          doDelivery();
        }
      } else if (option == JOptionPane.NO_OPTION) {
        doDelivery();
      } else {
        return;
      }
    }

    String guestName = registeredGuest.getName() + com.floreantpos.POSConstants.DELIVERY_;

    String notes = registeredGuest.getTelephone() + "|" + registeredGuest.getAddressLine1();

    if (!registeredGuest.getAddressLine2().isEmpty()) {
      notes = notes + " - " + registeredGuest.getAddressLine2();
    }

    if (!registeredGuest.getAddressLine3().isEmpty()) {
      notes = notes + " - " + registeredGuest.getAddressLine3();
    }

    notes = notes + "|";

    Application application = Application.getInstance();

    Ticket ticket = new Ticket();
    ticket.setTableNumber(Ticket.TAKE_OUT);
    ticket.setGuest(guestName);
    ticket.setRegisteredGuest(registeredGuest.getId());
    ticket.setNotes(notes);
    ticket.setTerminal(application.getTerminal());
    ticket.setOwner(Application.getCurrentUser());
    ticket.setShift(application.getCurrentShift());

    Calendar currentTime = Calendar.getInstance();
    ticket.setCreateDate(currentTime.getTime());
    ticket.setCreationHour(currentTime.get(Calendar.HOUR_OF_DAY));

    Double deliveryCharge = registeredGuest.getDeliveryCharge();
    if (deliveryCharge != 0) {
      TicketItem ticketItem = new TicketItem();
      ticketItem.setTicket(ticket);
      ticketItem.setBeverage(Boolean.FALSE);
      ticketItem.setBuffet(Boolean.FALSE);
      ticketItem.setCategoryName(com.floreantpos.POSConstants.DELIVERIES);
      ticketItem.setDiscountAmount(Double.valueOf(0));
      ticketItem.setDiscountRate(Double.valueOf(0));
      ticketItem.setGroupName(com.floreantpos.POSConstants.DELIVERIES);
      ticketItem.setHasModifiers(Boolean.FALSE);
      ticketItem.setItemCount(1);
      ticketItem.setItemId(0);
      ticketItem.setModifiedTime(currentTime.getTime());
      ticketItem.setName(com.floreantpos.POSConstants.DELIVERY);
      ticketItem.setPrintedToKitchen(Boolean.FALSE);
      ticketItem.setShouldPrintToKitchen(Boolean.FALSE);
      ticketItem.setSubtotalAmount(deliveryCharge);
      ticketItem.setSubtotalAmountWithoutModifiers(deliveryCharge);
      ticketItem.setTableRowNum(0);
      ticketItem.setTaxAmount(Double.valueOf(0));
      ticketItem.setTaxAmountWithoutModifiers(Double.valueOf(0));
      ticketItem.setTaxRate(Double.valueOf(0));
      ticketItem.setTotalAmount(Double.valueOf(0));
      ticketItem.setTotalAmountWithoutModifiers(Double.valueOf(0));
      ticketItem.setUnitPrice(deliveryCharge);
      ticketItem.setPaymentItem(Boolean.FALSE);

      ticket.addToticketItems(ticketItem);
    }

    OrderView.getInstance().setCurrentTicket(ticket);
    RootView.getInstance().showView(OrderView.VIEW_NAME);
  }

  private void doShowManagerWindow() {
    ManagerDialog dialog = new ManagerDialog();
    dialog.open();
  }

  private void doShowECFWindow() {
    if (BematechMP2100.impressoraFiscalLigada()) {
      ECFDialog dialog = new ECFDialog();
      dialog.open();
    } else {
      POSMessageDialog.showError("Não é possível abrir a janela \"Funções do ECF\".\nVerifique a Impressora de Cupom Fiscal.");
    }
  }

  private void doShowTicketInfo() {
    List<Ticket> selectedTickets = openTicketList.getSelectedTickets();
    if (selectedTickets.isEmpty() || selectedTickets.size() > 1) {
      POSMessageDialog.showMessage(POSConstants.SELECT_A_TICKET_FROM_THE_OPEN_TICKET_LIST);
      return;
    }

    Ticket ticket = selectedTickets.get(0);

    TicketDetailDialog dialog = new TicketDetailDialog(Application.getPosWindow(), true);
    dialog.setButtonPanelVisible(false);
    dialog.setBalanceDuePanelVisible(false);
    dialog.setTicket(ticket);
    dialog.pack();
    dialog.open();
  }

  private void doGroupSettle() {
    List<Ticket> selectedTickets = openTicketList.getSelectedTickets();
    if (selectedTickets.size() < 2) {
      POSMessageDialog.showError(POSConstants.YOU_MUST_SELECT_TWO_OR_MORE_TICKET_FOR_GROUP_SETTLE);
      return;
    }

    boolean ticketRemoved = false;
    for (int i = 0; i < selectedTickets.size(); i++) {
      if (selectedTickets.get(i).isPaymentTicket() || selectedTickets.get(i).getPaidAmount() != 0 || selectedTickets.get(i).getTableNumber() < 0) {
        selectedTickets.remove(i);
        i -= 1;

        ticketRemoved = true;
      }
    }

    if (selectedTickets.isEmpty()) {
      POSMessageDialog.showError("Não há pedidos para fechar.\nOs pedidos selecionados são Pedidos de Pagamento, Pedidos com pagamento parcial registrado ou Pedidos para Entrega/Retira.");
      return;
    }

    if (ticketRemoved) {
      POSMessageDialog.showError("Pedidos de Pagamento, Pedidos com pagamento parcial registrado ou Pedidos para Entrega/Retira não podem ser fechados junto com outros Pedidos.");
      return;
    }
    
    if (Application.isSaveTaxId()) {
      taxId = POSUtil.getTaxId();
    }    

    PaymentTypeSelectionDialog dialog = new PaymentTypeSelectionDialog(taxId);
    dialog.setSize(250, 400);
    dialog.open();

    if (!dialog.isCanceled()) {

      for (int i = 0; i < selectedTickets.size(); i++) {
        Ticket ticket = selectedTickets.get(i);
        ticket = TicketDAO.getInstance().initializeTicket(ticket);
        selectedTickets.set(i, ticket);
      }

      SettleTicketView view = SettleTicketView.getInstance();
      view.setPaymentView(dialog.getSelectedPaymentView());
      view.setTicketsToSettle(selectedTickets);
      RootView.getInstance().showView(SettleTicketView.VIEW_NAME);
    }
  }

  private void doTableSettle() {
    List<Ticket> selectedTickets = openTicketList.getSelectedTickets();
    if (selectedTickets.isEmpty() || selectedTickets.size() > 1) {
      POSMessageDialog.showMessage(com.floreantpos.POSConstants.SELECT_ONE_REQUEST_TO_CLOSE);
      return;
    }

    List<Ticket> selectedTable = openTicketList.getSelectedTableTickets();

    boolean ticketRemoved = false;
    for (int i = 0; i < selectedTable.size(); i++) {
      if (selectedTable.get(i).isPaymentTicket() || selectedTable.get(i).getPaidAmount() != 0 || selectedTable.get(i).getTableNumber() < 0) {
        selectedTable.remove(i);
        i -= i;

        ticketRemoved = true;
      }
    }

    if (selectedTable.isEmpty()) {
      POSMessageDialog.showError("Não há pedidos para fechar.\nOs pedidos selecionados são Pedidos de Pagamento, Pedidos com pagamento parcial registrado ou Pedidos para Entrega/Retira..");
      return;
    }

    if (ticketRemoved) {
      POSMessageDialog.showError("Pedidos de Pagamento, Pedidos com pagamento parcial registrado ou Pedidos para Entrega/Retira não podem ser fechados junto com outros Pedidos.");
      return;
    }

    if (Application.isSaveTaxId()) {
      taxId = POSUtil.getTaxId();
    }    
    
    PaymentTypeSelectionDialog dialog = new PaymentTypeSelectionDialog(taxId);
    dialog.setSize(250, 400);
    dialog.open();

    if (!dialog.isCanceled()) {

      for (int i = 0; i < selectedTable.size(); i++) {
        Ticket ticket = selectedTable.get(i);
        ticket = TicketDAO.getInstance().initializeTicket(ticket);
        selectedTable.set(i, ticket);
      }

      SettleTicketView view = SettleTicketView.getInstance();
      view.setPaymentView(dialog.getSelectedPaymentView());
      view.setTicketsToSettle(selectedTable);
      RootView.getInstance().showView(SettleTicketView.VIEW_NAME);
    }
  }

  public void updateView() {
    Integer ecfStatus = Application.getECFStatus();
    Boolean isTestSystem = Application.isTestSystem();
    
    if (PrintConfig.isPrintReceiptEnabled() && (ecfStatus != 0 || isTestSystem)) {
      btnPrintTicket.setEnabled(true);
    } else {
      btnPrintTicket.setEnabled(false);
    }
    User user = Application.getCurrentUser();
    UserType userType = user.getNewUserType();
    if (userType != null) {
      Set<UserPermission> permissions = userType.getPermissions();
      if (permissions != null) {
        btnNewTicket.setEnabled(false);
        btnBackOffice.setEnabled(false);
        btnEditTicket.setEnabled(false);
        btnGroupSettle.setEnabled(false);
        btnTableSettle.setEnabled(false);
        btnManager.setEnabled(false);
        btnECF.setEnabled(false);
        btnDelivery.setEnabled(false);
        btnReopenTicket.setEnabled(false);
        btnSettleTicket.setEnabled(false);
        btnSplitTicket.setEnabled(false);
        btnTakeout.setEnabled(false);
        btnVoidTicket.setEnabled(false);
        btnGuestSettle.setEnabled(false);

        for (UserPermission permission : permissions) {
          if (permission.equals(UserPermission.VOID_TICKET) && (ecfStatus != 0 || isTestSystem)) {
            btnVoidTicket.setEnabled(true);
          } else if (permission.equals(UserPermission.DELIVERY) && (ecfStatus != 0 || isTestSystem)) {
            btnDelivery.setEnabled(true);
          } else if (permission.equals(UserPermission.SETTLE_TICKET) && (ecfStatus == 2 || isTestSystem)) {
            btnSettleTicket.setEnabled(true);
            btnGroupSettle.setEnabled(true);
            btnTableSettle.setEnabled(true);
            btnGuestSettle.setEnabled(true);
            if (!isTestSystem) {
              btnECF.setEnabled(true);
            }
          } else if (permission.equals(UserPermission.REOPEN_TICKET) && (ecfStatus == 2 || isTestSystem)) {
            btnReopenTicket.setEnabled(true);
          } else if (permission.equals(UserPermission.PERFORM_MANAGER_TASK)) {
            btnManager.setEnabled(true);
          } else if (permission.equals(UserPermission.SPLIT_TICKET) && (ecfStatus != 0 || isTestSystem)) {
            btnSplitTicket.setEnabled(true);
          } else if (permission.equals(UserPermission.TAKE_OUT) && (ecfStatus != 0 || isTestSystem)) {
            btnTakeout.setEnabled(true);
          } else if (permission.equals(UserPermission.VIEW_BACK_OFFICE)) {
            btnBackOffice.setEnabled(true);
          } else if (permission.equals(UserPermission.EDIT_TICKET) && (ecfStatus != 0 || isTestSystem)) {
            btnEditTicket.setEnabled(true);
          } else if (permission.equals(UserPermission.CREATE_NEW_TICKET) && (ecfStatus != 0 || isTestSystem)) {
            btnNewTicket.setEnabled(true);
          }
        }
      }
    }

    updateTicketList();
  }

  private void updateTicketList() {
    User user = Application.getCurrentUser();

    TicketDAO dao = TicketDAO.getInstance();
    List<Ticket> openTickets = null;

    boolean showAllOpenTicket = false;
    if (user.getNewUserType() != null) {
      Set<UserPermission> permissions = user.getNewUserType().getPermissions();
      if (permissions != null) {
        for (UserPermission permission : permissions) {
          if (permission.equals(UserPermission.VIEW_ALL_OPEN_TICKET)) {
            showAllOpenTicket = true;
            break;
          }
        }
      }
    }

    if (showAllOpenTicket) {
      openTickets = dao.findOpenTickets();
    } else {
      openTickets = dao.findOpenTicketsForUser(user);
    }
    openTicketList.setTickets(openTickets);

    lblUserName.setText(POSConstants.WELCOME + " " + user.toString() + ". " + POSConstants.YOU + " " + POSConstants.HAVE + " " + openTickets.size() + " " + POSConstants.TICKETS + " " + POSConstants.OPEN.toLowerCase());
  }

  private com.floreantpos.swing.PosButton btnBackOffice;
  private com.floreantpos.swing.PosButton btnEditTicket;
  private com.floreantpos.swing.PosButton btnGroupSettle;
  private com.floreantpos.swing.PosButton btnTableSettle;
  private com.floreantpos.swing.PosButton btnInfo;
  private com.floreantpos.swing.PosButton btnLogout;
  private com.floreantpos.swing.PosButton btnManager;
  private com.floreantpos.swing.PosButton btnECF;
  private com.floreantpos.swing.PosButton btnNewTicket;
  private com.floreantpos.swing.PosButton btnDelivery;
  private com.floreantpos.swing.PosButton btnPrintTicket;
  private com.floreantpos.swing.PosButton btnReopenTicket;
  private com.floreantpos.swing.PosButton btnSettleTicket;
  private com.floreantpos.swing.PosButton btnShutdown;
  private com.floreantpos.swing.PosButton btnSplitTicket;
  private com.floreantpos.swing.PosButton btnTakeout;
  private com.floreantpos.swing.PosButton btnVoidTicket;
  private com.floreantpos.swing.PosButton btnGuestSettle;
  private javax.swing.JLabel lblUserName;
  private com.floreantpos.ui.TicketListView openTicketList;

  @Override
  public void setVisible(boolean aFlag) {
    super.setVisible(aFlag);

    if (aFlag) {
      updateView();
      ticketListUpdater.start();
    } else {
      ticketListUpdater.stop();
    }
  }

  public void actionPerformed(ActionEvent e) {
    Object source = e.getSource();
    if (source == btnBackOffice) {
      doShowBackoffice();
    }
    if (source == btnEditTicket) {
      doEditTicket();
    }
    if (source == btnGroupSettle) {
      doGroupSettle();
    }
    if (source == btnTableSettle) {
      doTableSettle();
    }
    if (source == btnInfo) {
      doShowTicketInfo();
    }
    if (source == btnLogout) {
      doLogout();
    }
    if (source == btnManager) {
      doShowManagerWindow();
    }
    if (source == btnECF) {
      doShowECFWindow();
    }
    if (source == btnNewTicket) {
      doCreateNewTicket();
    }
    if (source == btnDelivery) {
      doDelivery();
    }
    if (source == btnPrintTicket) {
      doPrintTicket();
    }
    if (source == btnReopenTicket) {
      doReopenTicket();
    }
    if (source == btnSettleTicket) {
      doSettleTicket();
    }
    if (source == btnShutdown) {
      doShutdown();
    }
    if (source == btnSplitTicket) {
      doSplitTicket();
    }
    if (source == btnTakeout) {
      doTakeout();
    }
    if (source == btnVoidTicket) {
      doVoidTicket();
    }
    if (source == btnGuestSettle) {
      doGuestSettle();
    }
  }

  private class TicketListUpdaterTask implements ActionListener {

    public void actionPerformed(ActionEvent e) {
      updateTicketList();
    }
  }
}
